package com.xy.shop.common.aop;

import com.alibaba.fastjson.JSON;
import com.xy.shop.common.annotation.OperLog;
import com.xy.shop.common.utils.IpUtil;
import com.xy.shop.common.utils.WebUtil;
import com.xy.shop.system.entity.User;
import com.xy.shop.web.entity.OperationLog;
import com.xy.shop.web.service.OperationLogService;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Author jxp
 **/
@Aspect
@Component
public class OperLogAspect {
    @Autowired
    private WebUtil webUtil;

    @Autowired
    private OperationLogService operationLogService;

    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.xy.shop.common.annotation.OperLog)")
    public void operLogPoinCut() {
    }

    /**
     * 正常返回通知，拦截用户操作日志，连接点正常执行完成后执行， 如果连接点抛出异常，则不会执行
     *
     * @param joinPoint 切入点
     * @param keys      返回结果
     */
    @AfterReturning(value = "operLogPoinCut()", returning = "keys")
    public void saveOperLog(JoinPoint joinPoint, Object keys) {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);
        try {
            OperationLog operlog = new OperationLog();
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();
            // 获取操作
            OperLog opLog = method.getAnnotation(OperLog.class);
            if (opLog != null) {
                // 操作模块
                operlog.setOperModul(opLog.operModul());
                // 操作描述
                operlog.setOperDesc(opLog.operDesc());
            }

            // 请求的参数
            Map<String, String> rtnMap = converMap(request.getParameterMap());
            if(rtnMap.containsKey("password")){
                //不监控用户的密码
                rtnMap.put("password","no");
            }
            // 将参数所在的数组转换成json
            String params = JSON.toJSONString(rtnMap);
            // 请求参数
            operlog.setRequestParam(params);
            // 返回结果
            operlog.setResponseParam(JSON.toJSONString(keys));
            // 请求用户名称
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            operlog.setOperName(user.getName());

           // operlog.setAppId(webUtil.getAppId(user.getLoginName()));
            operlog.setAppId(0);
            // 请求IP
            operlog.setOperIp(IpUtil.getIpAddr(request));
            // 请求URI
            operlog.setRequestUri(request.getRequestURI());
            // 创建时间
            operlog.setCreateTime(new Date());
            operationLogService.insert(operlog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 转换request 请求参数
     *
     * @param paramMap request获取的参数数组
     */
    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }
}
